perm filename PLAY.FAI[M11,LCS] blob sn#404803 filedate 1978-12-15 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00008 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002		TITLE	PLAY  DOROTHY BENDER MEMORIAL TITLE 1969,1975,77(LCS)*******
C00013 00003	entry DACPLA
C00016 00004	 Accumulators, temp storage
C00019 00005	 Error codes
C00025 00006	 DACPLA
C00030 00007	 WAIT1 - Wait for a buffer done message
C00032 00008	 DACREL - release the device
C00033 ENDMK
C⊗;
	TITLE	PLAY;  DOROTHY BENDER MEMORIAL TITLE 1969,1975,77(LCS)*******

;************** LOAD WITH 'DACPLA.FAI' ****** (IT MAY BE ON [SIX,MUS] ) *******

;  ROUTINE TO READ THE OUTPUT FROM THE MUSIC
;  PROGRAM AND CALL THE D-A CONVERTER TO PLAY.
;  
;  NAME OF THE FILE TO BE INPUTTED IS 'TEST.SND',
;  THE FIRST RECORD OF WHICH CONTAINS THE
;  NUMBER OF WORDS OF DATA IN THE ENTIRE DISK FILE.

	ENTRY PLAY
A   ←   1     ;WORK
B   ←   2     ;WORK
T1  ←   4     ; TEMP FOR ADSMAP (JAM)
REP ← 6;	;FOR REPLAY USETI
P ← 17
↓DSKCH ←1             ;DISK CHANNEL FOR INPUT
↓ADCHN  ←2             ;D-A CHANNEL FOR OUTPUT
↓SIXCH ←3             ;SIX CHANNEL FOR RUNNING DAC
PDL:	BLOCK 40
	OPDEF	READCH [51B8]
        OPDEF   MESSAGE[51B8!3B12]

;;EXTERNAL DACINI,DACPLA,DACWAI,DACREL
;External integer procedure DACINI(Integer dskCH,sixchn,dacchn,clock,pack,nchns,waitflag(0));
;External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));
;External integer procedure DACWAI;
;External integer procedure DACREL;

PLAY:	0
BEG:	CALLI	0,0         ;RESET I/O DEVICES
	MOVE 10,'DSK   '    ;DEVICE NAME
	MOVE 6,['TEST  ']
	MOVE 7,['SND   ']
	MOVE 10,['DSK   ']
 	SETZM	DIR+3    ;FOR RESTART
	SETZM   DEVNAM   ;DEVICE NAME
	SETZM SAVSPD#	;SAVES SPEED FOR REPLAYS
;;	OUTSTR[ASCIZ/
;;FILE NAME -- /]  
	SETO 5,		;FLAG FOR EXTENSIONS
DIREC:	SETZM DIR+1
	SETZM DIR
FLNM:	MOVE  2,[POINT 6,DIR]
	JRST LX	;;;;	JRST GOT
EXT:	MOVE 2,[POINT 6,DIR+1]
	SETZ 5,
GOT:	INCHWL	1
	CAIN  1,15	; A CR?
	JRST  GOT
	CAIL	1,60		; CHECKS FOR GOOD CHARS.
	CAIN	1,":"		;LOOK FOR DEVICE NAME:
	JRST	LX  
	cail   1,"a"		;change lower case to upper
	SUBI	1,40
	SUBI	1,40
	IDPB	1,2
	JRST	GOT
LX:	JUMPE 5,LZ
	SKIPN DIR
	MOVEM 6,DIR
	CAIN  1,56 	; 56='.'
	JRST EXT
	CAIE 1,":"	;LOOK FOR DEV. NAME
	JRST LZ  
	MOVE 10,DIR	;PUT 'FILE NAME' IN AS DEVICE
	JRST DIREC	;NOW GO BACK AND START OVER
LZ:	SKIPN DIR+1
	MOVEM 7,DIR+1
MESS:	MOVEM 10,DEVNAM
	MOVEM .+3
	MOVE	P,[IOWD 40,PDL]
 	OPEN 	DSKCH,[17  ;MODE
		DEVNAM:	0
 		0]          ;NO BUFFER HEADERS
	HALT	BEG         ;RESTART IF DEVICE IS UNAVAILABLE

;;	MESSAGE [ASCIZ/
;;TYPE <S> TO CHANGE SPEED.     TYPE <Rn> TO REPEAT n TIMES. /]
	SETZM REP	; FOR SPEED CHNGS WITH HEADER
	MOVEI A,1
	DPB	A,[POINT 2,DACPAR,35]
	JRST SPD
SPEED:	MESSAGE [ASCIZ/PEED
0=6.4K  1=12.8  2=25.6  3=51.2  4=102.8  5=204.8  /]
	READCH A
	CAIN A,15		; A CR?
	JRST LF			; GET THE LF
	CAILE A,"5"		;IS IT 1 - 5?
	JRST SPEED 		; BAD SPEED, TRY AGAIN.
SPD3:	DPB A,[POINT 3,DACPAR,26]		;PUT AWAY THE SPEED
	JRST SPD
HOME:	HRRZ 1,120		;GET STARTING ADDRESS FOR RETURN HOME
	MESSAGE [ASCIZ/
/]
	JRST (1)		;GO THERE.
LF:	READCH A		;GET THE LF
SPD:	MESSAGE [ASCIZ/

PLAY? /]
	SETOM REPT#		;FOR MULTIPLE PLAYS WITH Rn
	READCH  A
	CAIN A,"X"
;;	CALLI 12   	;X=EXIT,   MUST EXIT BECAUSE CHNS ARE CONFUSED.
	JRST HOME
	CAIE A,"s"
	CAIN A,"S"
	JRST SPEED
	CAIN A,15	; IS IT A CRLF???
	JRST PLA2
	CAIn A,"r"		;TYPE Rn TO REPEAT n TIMES, NO PAUSE
	jrst rep3
	CAIE A,"R"		;TYPE Rn TO REPEAT n TIMES, NO PAUSE
	JRST PLA2		;ELSE GO PLAY SAME AS LAST TIME
REP3:	MESSAGE [ASCIZ/EPEAT  /]
	READCH A		;GET NUM FOLLOWING R.
	SUBI A,"0"		;MAKE BIN.
	CAILE A,=9		;IF(A.GT.9)A=1  TRAPS "G"  ETC.
	MOVEI A,1
	MOVNM A,REPT		;REPEATS UP TO 9 TIMES.
	MOVE A,SAVSPD		;GET BACK SPEED.
PLA2:	SETZM DIR+3
	LOOKUP	DSKCH,DIR   

	JRST	[MESSAGE[ASCIZ/
		*** MUSIC FILE NOT FOUND/]
		JRA 16,16]        ;RETURN IF FILE IS MISSING
;;;		CALLI  12]        ;EXIT IF FILE IS MISSING

XOPEN:	OPEN	ADCHN,[1B27+000	;MODE
         	'DAC   '        ;DEVICE NAME
 		0]              ;NO BUFFER HEADERS
	SKIPA
	JRST GOTCHA		;GO AHEAD
        MESSAGE [ASCIZ/
WAITING FOR DAC------ /]
	OPEN  ADCHN,[1B26+000	;WE'LL WAIT FOR IT
		  'DAC   '
		  0]
	0			;NO FAILURE POSSIBLE?????
GOTCHA:	PUSH P,[DSKCH]
	PUSH P,[SIXCH]
	PUSH P,[ADCHN]
	LDB B,[POINT 3,DACPAR,26]		;PUT AWAY THE SPEED
	PUSH P,B
	LDB B,[POINT 2,DACPAR,29]			;12 OR 18 BIT
	PUSH P,B
	LDB B,[POINT 2,DACPAR,35]
	PUSH P,B
	PUSH P,[0]		; INTERROGATE USER AND WAIT FOR IT
	PUSHJ P,DACINI
SPWAR:	LOCK A,			;SPWAR:

	MESSAGE [ASCIZ/ GO? /]
	READCH A
	CAIN A,15
	READCH A		;FOR CRLF
	; READS TO FIND (AND IGNORE) HEADER.(1ST REC.)
DOIT:	SKIPE REP		;SKIP FIRST TIME
	JRST REPLA		;OMIT HEADER ON REPLAYS
	MOVEI REP,1 		;FOR REPLAY
	INPUT DSKCH,HEADER
	MOVEI A,BUF1-1
	MOVE B,1(A)
	CAME B,[525252525252]	; LOOKS FOR MAGIC NUMBER.
	JRST REPLA
	PUSH P,[DSKCH]
	PUSH P,[SIXCH]
	PUSH P,[ADCHN]
	HLRZ B,2(A)			;GET SPEED FROM LEFT HALF OF WD 2
	JUMPG B,SPOK
	MOVE B,2(A)			;FIND SRATE NUM FOR SPEED
	IDIVI B,=10000			;RIGHT FOR SPEED 0,1,2 ONLY
SPOK:	CAIL B,3		;LOOK FOR SPEED 3
	MOVEI B,3		;WON'T GET 4 OR 5
	MOVEM B,SAVSPD
	MOVE 10,B
	OUTSTR[ASCIZ/

SPEED=/]
	SOJL 10,SP0
	SKIPE 10
	JRST .+3
	OUTSTR[ASCIZ/1(12.8k)/]
	JRST SPDOK
	SOJL 10,SP3
	OUTSTR[ASCIZ/2(25.6k)/]
	JRST SPDOK
SP0:	OUTSTR[ASCIZ/0(6.4k)/]
	SKIPA
SP3:	OUTSTR[ASCIZ/3(51.2k)/]

SPDOK:	DPB B,[POINT 3,DACPAR,26]		;PUT AWAY THE SPEED
	PUSH P,B
	HRRZ B,3(A)			;GET BITS FROM RIGHT HALF OF WD 3
	DPB B,[POINT 2,DACPAR,29]			;12 OR 18 BIT
	PUSH P,B
	MOVE B,4(A)			;GET NCHNS FROM WD 4
	OUTSTR[ASCIZ/ -- NCHNS=/]
	MOVE 10,B
	SOJE 10,NCH1
	SOJE 10,NCH2
	OUTSTR[ASCIZ/4
/]
	JRST OK2
NCH1:	OUTSTR[ASCIZ/1
/]
	SKIPA
NCH2:	OUTSTR[ASCIZ/2
/]
OK2:	DPB B,[POINT 2,DACPAR,35]
	PUSH P,B
	PUSH P,[0]		; INTERROGATE USER IF DAC NOT AVAILABLE
	PUSHJ P,DACINI		; INITIALIZE THE DAC, SET PARAMETERS
	MOVEI REP,2		;FOR REPLAY
REPLA:	USETI DSKCH,(REP)	;REP=1 IF NO HEADER, =2 WITH HEADER.
LNTH:	movs a,DIR+3		;get length of file.
	CAIN REP,2		;WAS THERE A HEADER?
	ADDI A,200		;YES, SUBTRACT IT FROM WDCNT.
	movnm a,nwd
;-----------------------------------------------------

	;BEGIN MAIN BODY OF PROGRAM

	MOVE T1,[647001,,0]	;FOR AUDIO CH.1  NOV. 11, 1977  LCS
;;;	MOVE T1,[647003,,0]     ;FOR AUDIO CH. 3
	ADSMAP T1,	; SET AUDIO SWITCH TEMPORARILY TO DAC (JAM 7/24/75)
			; THE OPTIONS WE ASKED FOR ARE TEMPORARY, WAIT FOR
			; PAGE TO FINISH, DON'T INTERRUPT WITH MORE PAGES,
			; DELAY BEEPS TO END OF XFR.
	OUTSTR [ASCIZ /
TO DAC . . ./]
	PUSH P,REP	; SAVE OVER CALL
	SETZ B,
	CAIN REP,2
	MOVEI B,200
	PUSH P,B
	PUSH P,NWD
	PUSH P,[0]
	PUSH P,[0]
	PUSHJ P,DACPLA
	POP P,REP	; GET REP BACK

DONE:	AOSGE REPT		;UPDATE REPT
	JRST REPLA		;WE PLAY AGAIN IF REPT .LT.0
	PUSHJ P,DACWAI
	PUSHJ P,DACREL
	close dskCH,		;END OF PROGRAM.
	releas adchn,
	OUTSTR [ASCIZ / DONE!
/]
	SETO T1,
	ADSMAP T1,	; RESET AUDIO SWITCH CONNECTION TO PERMANENT (JAM 7/24/75)
	UNLOCK
	jrst SPD


; STORAGE:

NWD:	0			;FOR NUMBER OF WORDS OF INPUT.

DIR:	0    			;NAME
	0			;EXTENSION
	0			;INFORMATION ON FILE
	0			;PROJECT PROG#
HEADER:	IOWD =128,BUF1
	0
BUF1:	BLOCK =128
DACPAR:	1001		;SPEED 0=6.4K, 1=12.8, 2=25.6, 3=51.2, 4=102.4, 5=
	0
	0
;entry DACPLA
;;title DACPLA
;;internal DACINI,DACPLA,DACWAI,DACREL
external DSK6RD,DSK6WR,MESINI
.library JAMLIB.REL[SUB,SYS]
comment ⊗

External integer procedure DACINI(Integer dskchn,sixchn,dacchn,clock,pack,nchns,waitflag(0));
External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));
External integer procedure DACWAI;
External integer procedure DACREL;

DACINI

Must have disk open on channel DSKCHN. It will open the SIX and the DAC. Afterwards
it will set the DAC parameters to CLOCK, PACK, and NCHNS. It will then claim
buffers on the 6 and lock your KL10 job into core. Returns zero or -1 on success:
-1 means it had to wait for the DAC. Returns error 1 for user didn't want to
wait for the DAC and 2 if there was not enough core on the SIX.
The WAITFLAG determines whether DACINI will query the user as to whether he wants
to wait for the DAC. 0 means interrogate user and wait if he asks, 1 means always
wait (without asking) and -1 means never wait, never ask.
Disk must be opened in mode 17 (dump mode). Can be disk, new or old format UDP.
Track and BLK in DACPLA are irrelevant except for old format UDP.
(will get illegal UUO if disk not opened in mode 17).

CLOCK is actually the clock code, not the clock rate. This is 0 for 6.4 Kc,
1 for 12.8 Kc, 2 for 25.6 Kc, 3 for 51.2 Kc, and 4 for 102.4 Kc. This is the
clock rate per channel (not the overall clock rate). Pack should be 0 for
12-bit or 1 for 18-bit.

DACPLA

Queues up the sound in the dsk channel from word number STWORD for a total
of NWDS words. Transfer may still be running when this routine exits.

DACWAI

This waits for any transfers which were running to be finished. After
this call, the DAC will be idle.

DACREL

This releases the DAC, stops any transfer which might be running, and
releases the buffers on the six. It will release the SIX and the DAC.

⊗
; Accumulators, temp storage

↓ac1←4
↓ac2←5
↓ac3←6
↓ac4←7
↓ac5←10
↓ac6←11
↓ac7←13
↓ac8←14
↓ac9←15
↓p←17

.insert MESDEF[SIX,MUS]		;WHAT DOES THIS DO??

adr:	block 2		; For IOWDS and stuff
data:	block 3		; For messages
dacchn:	0	; Channel number for DAC
sixchn:	0	;    " for SIX
dskchn:	0	;    " for DSK


; Message codes going to DAC

MSPAR←←1010	; SET PARAMETERS. TAKES 9-BIT DATUM
MSTBUF←←1011	; START BUFFER. TAKES WCMA AS DATUM.
MSTOP←←1012	; DROP EVERYTHING
MQBUF←←1013	; QUEUE BUFFER BUT DON'T START IT
MFSTB←←1015	; FIRST BUFFER COMING

; Message codes coming from DAC

MBDONE←←1020	; BUFFER DONE.
MHUNG←←1021	; DEVICE IS HUNG.
MDMISS←←1022	; HARDWARE DATA MISSED SEEN
MBMISS←←1023	; BUFFER MISSED (RAN OFF END WITH NO WCMA READY)
MBOOB←←1025	; BUFFER OUT OF BOUNDS

DACDEV←←2	; DIGITAL-ANALOG CONVERTER DEVICE NUMBER

; = SPEED*1000+PACK*100+NCHANS
; NCHANS = 1 FOR MONO	(2-BIT NUMBER)
;	 = 2 FOR STEREO
;	 = 0,3 FOR QUAD
; PACK = 0,3 FOR 12 BIT  (2-BIT NUMBER)
;      = 1 FOR 16 BIT (HALFWORD MODE)
;      = 2 FOR FLOATING PT. INCREMENTAL
; SPEED = 0 FOR 6.4 KC	(3-BIT NUMBER)
;       = 1 FOR 12.8 KC
;       = 2 FOR 25.6 KC
;       = 3 FOR 51.2 KC
;       = 4 FOR 102.4 KC
;       = 5 FOR 204.8 KC

; Other storage . . .

oldfmt:	0	; 0 for New fmt, ≠0 for old fmt udp
wcmas:
wcma1:	0	; WCMA for buffer 1
wcma2:	0	; for buffer 2
wcma3:	0	; Set to zero if not needed
nxtwc:	0	; 0, 1, or 2, for next buffer to fill
nq:	0	; Number of xfrs in queue now (0, 1, 2, or 3)

trklen←←=18*=128	; Length of track for new fmt UDP or DSK
otrklen←←40+trklen	; Same for old fmt UDP
↓ntrks←←6		; Number of tracks per buffer
;↓ntrks←←10		; Number of tracks for SIXSYS without DDT
waited:	0	; Set to -1 if we waited for DAC
; Error codes

enodac←←1	; User doesn't want to wait for DAC
enocor←←2	; Not enuf core on PDP-6
didwait←←-1	; Did have to wait for DAC

; DACINI
;External integer procedure DACINI(Integer dskchn,sixchn,dacchn,clock,pack,nchns,waitflag(0));

DACINI:	begin DACINI

watloc←←-1
ncloc←←-2
pakloc←←-3
clkloc←←-4
dacloc←←-5
sixloc←←-6
dskloc←←-7
pd←←10

nowait←←400
wait←←1000

	setzm waited
	move ac1,dskloc(p)
	movem ac1,dskchn
	dpb ac1,[point 4,dskc1,12]

	devchr ac1,		; if 100000 bit in LH is on, and
				; 200000 bit is off, is old-style udp
	setom oldfmt
	tlne ac1,100000
	tlne ac1,200000
	setzm oldfmt

	move ac1,sixloc(p)
	movem ac1,sixchn
	dpb ac1,[point 4,sixc1,12]
	dpb ac1,[point 4,sixc2,12]
	dpb ac1,[point 4,sixc3,12]
	dpb ac1,[point 4,sixc4,12]
	dpb ac1,[point 4,sixc5,12]
	dpb ac1,[point 4,sixc6,12]
	dpb ac1,[point 4,sixc7,12]
	dpb ac1,[point 4,sixc8,12]
	dpb ac1,[point 4,sixc9,12]
	dpb ac1,[point 4,sixc10,12]
	dpb ac1,[point 4,sixc11,12]
	dpb ac1,[point 4,sixc12,12]
	dpb ac1,[point 4,sixc13,12]
	dpb ac1,[point 4,sixc14,12]
	push p,ac1
	pushj p,mesini

	move ac1,dacloc(p)
	movem ac1,dacchn
	dpb ac1,[point 4,dacc1,12]
	dpb ac1,[point 4,dacc2,12]
	dpb ac1,[point 4,dacc3,12]
	dpb ac1,[point 4,dacc4,12]

dacc1:	init 0,nowait
	sixbit /DAC/
	0
	jrst [move ac1,watloc(p)
	      jumpl ac1,nodacx
	      jumpg ac1,dacc2
	      outstr [asciz /
DAC is busy. Will you wait?	/]
	      inchwl ac1
	      pushj p,rdlf
	      caie ac1,"y"
	      cain ac1,"Y"
	      jrst dacc2
nodacx:	      movei 1,enodac		; Give "no DAC" error message
	      jrst xit]
sixc1:	init 0,17
	sixbit /SIX/
	0
	jrst 4,.
			; = SPEED*1000+PACK*100+NCHANS
	move ac1,[mspar,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
	move ac1,clkloc(p)
	lsh ac1,=3
	or ac1,pakloc(p)
	lsh ac1,=6
	or ac1,ncloc(p)
	movem ac1,data+2
	move ac1,[iowd 3,data]
	movem ac1,adr
	setzm adr+1
sixc2:	output 0,adr

	movei ac1,ntrks*trklen
	skipe oldfmt
	movei ac1,ntrks*otrklen	; Get 4 tracks per buffer
	movem ac1,data+2
	movsi ac1,mgbuf
	hllm ac1,data
sixc3:	output 0,adr
sixc4:	output 0,adr
sixc5:	output 0,adr		; Ask for 3 buffers of identical size.
	movei ac2,2
sixc6:	input 0,adr		; Wait for message to come back
	hlrz ac1,data
	trne ac1,fncomp!fdmissed
	jrst [outstr [asciz /DACINI - Incomplete message from PDP-6
/]
	      jrst mbtest]
mbtest:	caie ac1,f6to10!mgbuf		; Ignore everything but buffer reply
	jrst sixc6
	skipl ac1,data+2
	jrst nocore		; Hmmm. No core?
	movem ac1,wcmas(ac2)
	sojge ac2,sixc6
	setzm nq		; Clear number of buffers in queue
	setzm nxtwc

	setz 1,
	skipe waited
	move 1,[didwait]	; Give -1 return for waited
xit:	adjsp p,-pd
	jrst @pd(p)

dacc2:	init 0,wait
	sixbit /DAC/
	0
	jrst 4,.
	setom waited
	jrst sixc1

nocore:	movsi ac1,mdblast	; Forget everything we ever know about device
	hllm ac1,data
	move ac1,[iowd 1,data]
	movem ac1,data+1
sixc7:	output 0,adr
	movei 1,enocore
dacc3:	release 0,		; Release dummy DAC device
	setzm wcma1
	setzm wcma2
	setzm wcma3
	jrst xit

rdlf:	cain ac1,12
	popj p,
rdlf1:	inchwl ac9
	cain ac9,175
	jrst isalt
	caie ac9,12
	jrst rdlf1
	popj p,

isalt:	outstr [asciz /
/]
	popj p,

bend DACINI
; DACPLA
;External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));

; Uses . . .

;External procedure DSK6RD(integer dchan,nwds,p3addr,track(0),blk(0));
;External procedure DSK6WR(integer dchan,nwds,p3addr,track(0),blk(0));

;DAC may be running when we enter.

DACPLA:	begin DACPLA

integer offset		; Number of words in first buffer to be ignored
integer track
integer block		; For old mode
integer nwltt		; Number of words left this track
integer ndwfb		; Number of words in first buffer (from disk) total
integer nwfb		; Number of data words in first buffer (for DAC)

blkloc←←-1
trkloc←←-2
nwdloc←←-3
stwloc←←-4
pd←←5

	setz 1,
	skipg nwdloc(p)		; Anybody home?
	jrst xit		; No, leave now
	skipe wcma1
	skipn wcma2
	jrst [movei 1,enocore
	      jrst xit]
	skipn wcma3
	jrst [movei 1,enocore
	      jrst xit]

	skipe oldfmt
	jrst isold
	move ac1,stwloc(p)
	move ac2,ac1
	andi ac2,177
	movem ac2,offset
	lsh ac1,-7
	addi ac1,1
↑dskc1:	useti 0,(ac1)

	move ac1,stwloc(p)
	idivi ac1,trklen
	movn ac2,ac2
	addi ac2,trklen
	movem ac2,nwltt

	addi ac2,<ntrks-1>*trklen
	movem ac2,nwfb
	jrst allgo

isold:	move ac1,trkloc(p)
	imuli ac1,otrklen
	move ac2,blkloc(p)
	caige ac2,1
	jrst nocorr
	addi ac1,40
	subi ac2,1
	lsh ac2,7
	addi ac1,(ac2)		; Convert to word number on UDP
nocorr:	add ac1,stwloc(p)
	idivi ac1,otrklen	; And back to track-block
	movem ac1,track
	movni ac3,(ac2)		; Pick up number of words used this track
	addi ac3,otrklen
	movem ac3,nwltt		; Set number words left this track
	addi ac3,<ntrks-1>*otrklen
	movem ac3,nwfb
	caige ac2,40
	jrst [setzm block
	      jrst setoff]
	subi ac2,40
	move ac1,ac2
	andi ac2,177
	lsh ac1,-7
	addi ac1,1
	movem ac1,block
setoff:	movem ac2,offset

allgo:	push p,dskchn
	move ac1,nwfb
	camle ac1,nwdloc-1(p)
	move ac1,nwdloc-1(p)	; Don't do any more than we have to!
	movem ac1,ndwfb
	add ac1,offset		; Make sure we get all of first record
	push p,ac1
	move ac2,nxtwc
	hrrz ac1,wcmas(ac2)
	push p,ac1
	push p,track
	push p,block
	move ac1,nq		; How many are queued?
	cail ac1,3		; If more than 3, must wait
	pushj p,wait1		; Wait until that first buffer is free
	pushj p,dsk6rd		; Fill it

	move ac2,nxtwc		; Pick up buffer number (0, 1, or 2)
	movn ac1,ndwfb		; This has been truncated to length of file
	addm ac1,nwdloc(p)	; Note that many more words gone by
	movs ac1,ac1		; Make up WCMA for transfer
	hrr ac1,wcmas(ac2)	; Put address of buffer on 6 in RH
	add ac1,offset		; Offset for partial first buffer (if any)
	movem ac1,data+2
	move ac1,[mstbuf,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
	move ac1,[iowd 3,data]
	movem ac1,adr
↑sixc8:	output 0,adr
	aos nq			; Note one more in the queue
	sosge ac1,nxtwc
	movei ac1,2
	movem ac1,nxtwc
	skipg nwdloc(p)
	jrst alldone

	setzm offset
	movei ac1,ntrks*trklen
	skipe oldfmt
	movei ac1,ntrks*otrklen
	movem ac1,nwfb

	movei ac1,ntrks
	addm ac1,track
	setzm block
	jrst allgo

alldone:setz 1,
xit:	adjsp p,-pd
	jrst @pd(p)

bend DACPLA
; WAIT1 - Wait for a buffer done message

WAIT1:	move ac1,[iowd 3,data]
	movem ac1,adr
sixc9:	input 0,adr
	hlrz ac1,data
	trne ac1,fncomp!fdmissed
	jrst [outstr [asciz /DACPLA - incomlete message from 6!
/]
	      jrst wattst]
wattst:	andi ac1,7777
	cain ac1,mhung
	jrst [outstr [asciz /DACPLA - DAC is HUNG!
/]
	      jrst gotit]	; Hung message takes place of done message
	cain ac1,mboob
	jrst [outstr [asciz /DACPLA - buffer out of bounds?!?!!?
/]
	      jrst gotit]	; this message also takes place of done message
	cain ac1,mdmiss
	jrst [outstr [asciz /DACPLA - DAC Data missed!
/]
	      jrst sixc9]
	cain ac1,mbmiss
	jrst [outstr [asciz /DACPLA - DAC buffer missed!
/]
	      jrst sixc9]
	caie ac1,mbdone
	jrst sixc9
gotit:	sosl nq			; Note one less in queue
cpopj:	popj p,
	outstr [asciz /DACPLA - Buffer queue underflow
/]
	jrst 4,cpopj

; DACWAI - Wait for all xfrs to finish

DACWAI:	skipg nq
	jrst sfstbm
	pushj p,wait1
	jrst dacwai

sfstbm:	move ac1,[fnowds!mfstb,,dacdev]
	movem ac1,data
	move ac1,[iowd 1,data]
	movem ac1,adr
sixc14:	output 0,adr		; Clear "buffers finished" count
	popj p,
; DACREL - release the device

DACREL:	move ac1,[iowd 1,data]
	movem ac1,adr
	move ac1,[fnowds!mdblast,,dacdev]
	movem ac1,data
sixc10:	output 0,adr
	move ac1,[iowd 3,data]
	movem ac1,adr
	move ac1,wcma1
	movem ac1,data+2
	move ac1,[mgivb,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
sixc11:	output 0,adr
	move ac1,wcma2
	movem ac1,data+2
sixc12:	output 0,adr
	move ac1,wcma3
	movem ac1,data+2
sixc13:	output 0,adr
	setzm wcma1
	setzm wcma2
	setzm wcma3
dacc4:	release 0,
	popj p,
END